﻿
using System.ComponentModel;
using System.Collections.Generic;
using System;

namespace DnPakExplorer {

	/// <summary>
	/// 角色模型
	/// </summary>
	public partial class Character  {
		public const int AppellationID = 1000;
		public const int HeroPropertyID = 1001;

		
		private int _jobId;
		private int _level;
		private int _herolLevel;

		/// <summary>
		/// 有”最大效果值“特性的属性集合
		/// </summary>
		private Dictionary<PropertyID, int> mMaxPropertyIDMap;

		/// <summary>
		/// 角色关闭事件
		/// </summary>
		public event EventHandler OnCharacterClosed;

		/// <summary>
		/// 角色名
		/// </summary>
		public string Name { get; set; }

		/// <summary>
		/// 角色应用的称号
		/// </summary>
		public Appellation Appellation {
			get { return EquipmentPanel[Character.AppellationID] as Appellation; }
			set { EquipmentPanel[Character.AppellationID] = value; }
		}

		/// <summary>
		/// 角色的职业id
		/// </summary>
		public int JobId {
			get { return _jobId; }
			private set {
				if (_jobId != value) {
					_jobId = value;
					InitPlayerMatrix();
					InitPlayerLevel();
				}
			}
		}

		/// <summary>
		/// 角色等级
		/// </summary>
		public int Level {
			get { return _level; }
			private set {
				if (_level != value) {
					_level = value;
					InitPlayerCommonLevel();
					InitPlayerLevel();
				}
			}
		}

		/// <summary>
		/// 角色的英雄等级
		/// </summary>
		public int HeroLevel {
			get { return _herolLevel; }
			set {
				if (_herolLevel != value) {
					EquipmentPanel[Character.HeroPropertyID] = new HerolProperty(value);
				}
				_herolLevel = value;
			}
		}

		/// <summary>
		/// 角色的职业名称
		/// </summary>
		public string JobName {
			get {
				for (int r=0; r<DnResourceUtil.JobTable.RecordCount; r++) {
					if (JobId == DnResourceUtil.JobTable.GetKey(r))
						return Util.FindUIString((int)DnResourceUtil.JobTable[r, "_JobName"]);
				}
				return "";
			}
		}

		/// <summary>
		/// 角色当前状态下（等级、职业）的固有基础属性（无需装备或者技能就有的，与生俱来就有的）
		/// </summary>
		int[] mPlayerBasePropery = new int[(int)PropertyID.ID_MAX];
		EquipmentPanel mEquipmentPanel;
		BagPanel mBagPanel;
		SkillPanel mPanel;
		/// <summary>
		///  角色当前状态下（等级、职业）属性转换比率，比如求属性a转换成属性b的加成为a×mPlayerMatrix[a][b]。
		///  智力、体质、敏捷和力量这四种属性可以转化成其他绝大部分的属性，但是没有其他任何属性转化成这样四种属性。
		/// </summary>
		float[][] mPlayerMatrix;

		float maxPysicalDefense;
		float maxCritical;
		float maxFinalDamage;
		float maxCriticalDamage;

		
		/// <summary>
		/// 创建一个角色
		/// </summary>
		/// <param name="jobId">角色职业id</param>
		/// <param name="level">角色等级</param>
		/// <param name="heroLevel">角色英雄等级</param>
		public Character(int jobId, int level, int heroLevel) {
			_jobId = jobId;
			_level = level;
			InitPlayerCommonLevel();
			InitPlayerLevel();
			InitPlayerMatrix();
			mEquipmentPanel = new EquipmentPanel(this);
			mBagPanel = new BagPanel(this);
			mPanel = new SkillPanel();
			HeroLevel = heroLevel;
			mMaxPropertyIDMap = new Dictionary<PropertyID, int>();
			mMaxPropertyIDMap.Add(PropertyID.PysicalDefense, 6);
			mMaxPropertyIDMap.Add(PropertyID.MagicDefense, 6);
			mMaxPropertyIDMap.Add(PropertyID.Critical, 7);
			mMaxPropertyIDMap.Add(PropertyID.CriticalResistance, 14);
			mMaxPropertyIDMap.Add(PropertyID.FinalDamage, 8);
			mMaxPropertyIDMap.Add(PropertyID.CriticalDamage, 12);
		}

		public void CloseCharacter() {
			if (OnCharacterClosed != null) {
				OnCharacterClosed(this, EventArgs.Empty);
			}
			OnCharacterClosed = null;
		}

		
		/// <summary>
		/// 角色当前等级下，某些属性的最大效果值。当某一属性（如果这个属性有这个特性）值达到最大效果值
		/// 时，其实际应用效果不会继续提升。
		/// </summary>
		void InitPlayerCommonLevel() {
			Dntable playerCommonLevelDnt = DnResourceUtil.PlayerCommonLevelTable;
			maxPysicalDefense = (float)playerCommonLevelDnt[Level, "_Cdefense"];
			maxCritical = (float)playerCommonLevelDnt[Level, "_Ccritical"];
			maxFinalDamage = (float)playerCommonLevelDnt[Level, "_Cfinaldamage"];
			maxCriticalDamage = (float)playerCommonLevelDnt[Level, "_CcriticalDamage"];
		}

		/// <summary>
		/// 角色等级初始化
		/// </summary>
		void InitPlayerLevel() {
			Dntable playerLevelDnt = DnResourceUtil.PlayerLevelTable;
			Dntable rebootplayerweighttable = DnResourceUtil.RebootPlayerWeightTable;
			int weightIndex = rebootplayerweighttable.IndexOfKey(JobId);
			int index = playerLevelDnt.IndexOfKey(JobId*100+Level);

			mPlayerBasePropery[(int)PropertyID.Strength] = (int)playerLevelDnt[index, "_Strength"];
			mPlayerBasePropery[(int)PropertyID.Agility] = (int)playerLevelDnt[index, "_Agility"];
			mPlayerBasePropery[(int)PropertyID.Intelligence] = (int)playerLevelDnt[index, "_Intelligence"];
			mPlayerBasePropery[(int)PropertyID.Stamina] = (int)playerLevelDnt[index, "_Stamina"];
			mPlayerBasePropery[(int)PropertyID.MP] = (int)playerLevelDnt[index, "_BaseMP"];
			mPlayerBasePropery[(int)PropertyID.MoveSpeed] = (int)(float)DnResourceUtil.RebootPlayerWeightTable[weightIndex, "_MoveSpeed"];
		}

		/// <summary>
		/// 初始化角色当前状态（职业、等级）下属性变化矩阵
		/// </summary>
		void InitPlayerMatrix() {
			Dntable rebootplayerweighttable = DnResourceUtil.RebootPlayerWeightTable;
			int index = rebootplayerweighttable.IndexOfKey(JobId);
			mPlayerMatrix = new float[(int)PropertyID.ID_MAX][];
			for (int i=0; i<mPlayerBasePropery.Length; i++) {
				mPlayerMatrix[i] = new float[(int)PropertyID.ID_MAX];
			}
			mPlayerMatrix[(int)PropertyID.Stamina][(int)PropertyID.HP] = (float)rebootplayerweighttable[index, "_HP"];
			mPlayerMatrix[(int)PropertyID.Strength][(int)PropertyID.MaxPysicalAttack] = (float)rebootplayerweighttable[index, "_StrengthAttack"];
			mPlayerMatrix[(int)PropertyID.Strength][(int)PropertyID.MinPysicalAttack] = (float)rebootplayerweighttable[index, "_StrengthAttack"];
			mPlayerMatrix[(int)PropertyID.Agility][(int)PropertyID.MaxPysicalAttack] = (float)rebootplayerweighttable[index, "_AgilityAttack"];
			mPlayerMatrix[(int)PropertyID.Agility][(int)PropertyID.MinPysicalAttack] = (float)rebootplayerweighttable[index, "_AgilityAttack"];
			mPlayerMatrix[(int)PropertyID.Intelligence][(int)PropertyID.MaxMagicAttack] = (float)rebootplayerweighttable[index, "_IntelligenceAttack"];
			mPlayerMatrix[(int)PropertyID.Intelligence][(int)PropertyID.MinMagicAttack] = (float)rebootplayerweighttable[index, "_IntelligenceAttack"];
			mPlayerMatrix[(int)PropertyID.Stamina][(int)PropertyID.PysicalDefense] = (float)rebootplayerweighttable[index, "_PhysicalDefense"];
			mPlayerMatrix[(int)PropertyID.Intelligence][(int)PropertyID.MagicDefense] = (float)rebootplayerweighttable[index, "_MagicDefense"];
			mPlayerMatrix[(int)PropertyID.Agility][(int)PropertyID.Critical] = (float)rebootplayerweighttable[index, "_Critical"];
			mPlayerMatrix[(int)PropertyID.Agility][(int)PropertyID.CriticalResistance] = (float)rebootplayerweighttable[index, "_CriticalResistance"];
			mPlayerMatrix[(int)PropertyID.Strength][(int)PropertyID.Stiff] = (float)rebootplayerweighttable[index, "_Stiff"];
			mPlayerMatrix[(int)PropertyID.Strength][(int)PropertyID.StiffResistance] = (float)rebootplayerweighttable[index, "_StiffResistance"];
			mPlayerMatrix[(int)PropertyID.Strength][(int)PropertyID.Stun] = (float)rebootplayerweighttable[index, "_Stun"];
			mPlayerMatrix[(int)PropertyID.Stamina][(int)PropertyID.StunResistance] = (float)rebootplayerweighttable[index, "_StunResistance"];
			mPlayerMatrix[(int)PropertyID.Strength][(int)PropertyID.CriticalDamage] = (float)rebootplayerweighttable[index, "_StrengthIntelligenceToCriticalDamage"];
			mPlayerMatrix[(int)PropertyID.Intelligence][(int)PropertyID.CriticalDamage] = (float)rebootplayerweighttable[index, "_StrengthIntelligenceToCriticalDamage"];
		}


		/// <summary>
		/// 获取“白字”属性值（“白字”是因为龙之谷游戏中这项属性的显示是白色字体的，因而得名，类似有“绿色”属性、“蓝色”属性），
		/// 计算方式：角色固有属性值+其他属性转化而来的属性值（比如智力可以按一定比例转化成魔法攻击、魔法防御和Mp等其他属性）
		/// </summary>
		/// <param name="pid">属性id</param>
		public double _GetWhiteProperty(PropertyID pid) {
			if (pid>=PropertyID.Strength && pid<=PropertyID.Stamina)
				return mPlayerBasePropery[(int)pid] ;	// 基础属性
			else
				return mPlayerBasePropery[(int)pid]	//其他属性 基础属性+转换属性
				+ GetProperty(PropertyID.Strength)*mPlayerMatrix[(int)PropertyID.Strength][(int)pid]
				+ GetProperty(PropertyID.Agility)*mPlayerMatrix[(int)PropertyID.Agility][(int)pid]
				+ GetProperty(PropertyID.Intelligence)*mPlayerMatrix[(int)PropertyID.Intelligence][(int)pid]
				+ GetProperty(PropertyID.Stamina)*mPlayerMatrix[(int)PropertyID.Stamina][(int)pid];
		}

		/// <summary>
		/// 获取“绿色”属性值，其意义为装备的直接加成，计算方式：装备基础属性+“白色属性”×装备百分比加成属性
		/// </summary>
		/// <param name="pid"></param>
		/// <returns></returns>
		public double _GetGreenProperty(PropertyID pid) {
			double equip = mEquipmentPanel.GetProperty(pid);
			int genProperty = PropertyUtil.GetGenProperty((int)pid);	// 百分比加成属性
			if (genProperty >= 0) {
				double gen = mEquipmentPanel.GetProperty((PropertyID)genProperty);
				return GetWhiteProperty(pid) * gen + equip * (1+gen);
			}
			return equip;
		}

		/// <summary>
		/// 获取“蓝色”属性，其意义为技能部分的加成属性
		/// </summary>
		/// <param name="pid"></param>
		/// <returns></returns>
		public double _GetBluePropery(PropertyID pid) {
			//if (JobId == 35) {
			//	if (pid == PropertyID.MinMagicAttack || pid == PropertyID.MaxMagicAttack) {
			//		return (GetWhiteProperty(pid)+GetGreenProperty(pid))*0.1f;
			//	} else if (pid == PropertyID.FireAttack) {
			//		return 0.2f;
			//	} else if (pid == PropertyID.Intelligence) {
			//		return (GetWhiteProperty(pid)+GetGreenProperty(pid))*0.5f;
			//	} else if (pid == PropertyID.HP) {
			//		return (GetWhiteProperty(pid)+GetGreenProperty(pid))*0.29f;
			//	}
			//} else if(JobId == 58){
			//	if (pid == PropertyID.MinPysicalAttack || pid == PropertyID.MaxPysicalAttack) {
			//		return (GetWhiteProperty(pid)+GetGreenProperty(pid))*0.1f;
			//	} else if (pid == PropertyID.FireAttack) {
			//		//return 0.2f;
			//	} else if (pid == PropertyID.Intelligence) {
			//		//return (GetWhiteProperty(pid)+GetGreenProperty(pid))*0.5f;
			//	} else if (pid == PropertyID.HP) {
			//		return (GetWhiteProperty(pid)+GetGreenProperty(pid))*0.29f;
			//	}
			//}
			SkillProperty sp = SkillNanel.GetProperty(pid);
			return (GetWhiteProperty(pid)+GetGreenProperty(pid))*sp.percentValue+sp.value;
		}

		/// <summary>
		/// 获取某些（如果有）属性的最终“应用比率”
		/// </summary>
		public double GetRateProperty(PropertyID pid) {
			if (IsRateProperty(pid)) {
				float max = (float)DnResourceUtil.PlayerCommonLevelTable[Level-1, mMaxPropertyIDMap[pid]];
				if (pid == PropertyID.FinalDamage) {
					double linearMax = max*0.41663633;
					double value = GetProperty(pid);
					if(value < linearMax){
						return Math.Pow(max, -2.2) * Math.Pow(linearMax, 2.2) / linearMax * value;
					}else
						return Math.Pow(max, -2.2) * Math.Pow(value, 2.2);
				}
				return GetProperty(pid)/max + SkillNanel.GetProperty(pid).rateValue;
			}
			return 0;
		}

		static bool round = true;

		/// <summary>
		/// 判断目标属性pid是否有最终的”应用比率“
		/// </summary>
		public bool IsRateProperty(PropertyID pid) {
			return mMaxPropertyIDMap.ContainsKey(pid);
		}

		public double GetWhiteProperty(PropertyID pid) {
			if (round && !PropertyUtil.IsPercentProperty((int)pid)) {
				return (int)_GetWhiteProperty(pid);
				//return System.Math.Round(_GetWhiteProperty(pid), 0);
			}
			return _GetWhiteProperty(pid);
		}

		public double GetGreenProperty(PropertyID pid) {
			if (round && !PropertyUtil.IsPercentProperty((int)pid)) {
				//return (int)_GetGreenProperty(pid);
				return (int)_GetGreenProperty(pid);
			}
			return _GetGreenProperty(pid);
		}

		public double GetBluePropery(PropertyID pid) {
			if (round && !PropertyUtil.IsPercentProperty((int)pid)) {
				return (int)_GetBluePropery(pid);
				//return System.Math.Round(_GetBluePropery(pid), 0);
			}
			return _GetBluePropery(pid);
		}

		/// <summary>
		/// 获取面板属性，计算方式：白色属性+绿色属性+蓝色属性
		/// </summary>
		/// <param name="pid"></param>
		public double GetProperty(PropertyID pid) {
			return GetWhiteProperty(pid)+GetGreenProperty(pid)+GetBluePropery(pid);
		}

		/// <summary>
		/// 角色的装备面板
		/// </summary>
		public EquipmentPanel EquipmentPanel {
			get { return mEquipmentPanel; }
		}


		/// <summary>
		/// 角色的技能面板
		/// </summary>
		public SkillPanel SkillNanel {
			get { return mPanel; }
		}

		/// <summary>
		/// 角色的背包面板
		/// </summary>
		public BagPanel BagPanel {
			get { return mBagPanel; }
		}


		
	}

	
}
